Skip to main content

Using themed icons in SPFx command bar extensions

·4 mins

Introduction

So you know how when you’re creating an SPFx command bar extension it’ll reference the “icons/request.png” file so you can create your own icons and add to your solution.

Awesome, right? - well yeah, if you’re an ISV and want to use your logo, but if you’re building a solution that you might not want branded with your logo, but just want to blend in to the platform - then it’s not so awesome.

In this post we’ll be taking a look at how to use Fluent UI icons as a logo in your command bar extension, including theme support!

Getting the SVG icon

Firstly we’ll need the SVG version of the icon we want to use, here I really like using Flicon by Chris Kent, simply find the icon you like (I’ll be using “FullHistory” in this example) under export you can download the SVG version of the icon.

Flicon

Next open the .SVG file in a text editor like NotePad++ and copy the contents, you should have something like this:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2048 2048"><path d="M896 512h128v512H896V512zM512 768H0V256h128v274q67-123 163-221t212-166T752 37t272-37q141 0 272 36t245 103 207 160 160 208 103 245 37 272h-128q0-123-32-237t-90-214-141-182-181-140-214-91-238-32q-129 0-251 36T546 267 355 428 215 640h297v128zm512 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm-863-657q36 129 105 239t166 194 214 140 250 74v130q-154-21-292-83t-250-158-193-224-123-278l123-34z" fill="#333333"></path></svg>

Encoding the SVG icon

Now paste that value here, it’s a tool that encodes SVGs so they can be used in SPFx extensions - the tool is built by Hugo Bernier

Pasting the contents into the tool will instantly encode it, and allow you to then copy the encoded value, it should look something along the lines of this

data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2048 2048'%3E%3Cpath d='M896 512h128v512H896V512zM512 768H0V256h128v274q67-123 163-221t212-166T752 37t272-37q141 0 272 36t245 103 207 160 160 208 103 245 37 272h-128q0-123-32-237t-90-214-141-182-181-140-214-91-238-32q-129 0-251 36T546 267 355 428 215 640h297v128zm512 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm-863-657q36 129 105 239t166 194 214 140 250 74v130q-154-21-292-83t-250-158-193-224-123-278l123-34z' fill='%23333333'%3E%3C/path%3E%3C/svg%3E

This value can be used as the iconImageUrl in your command bar extension manifest, like this:

"YOUR_COMMAND_NAME": {
  "title": { "default": "Command One" },
  "type": "command",
  "iconImageUrl": "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2048 2048'%3E%3Cpath d='M896 512h128v512H896V512zM512 768H0V256h128v274q67-123 163-221t212-166T752 37t272-37q141 0 272 36t245 103 207 160 160 208 103 245 37 272h-128q0-123-32-237t-90-214-141-182-181-140-214-91-238-32q-129 0-251 36T546 267 355 428 215 640h297v128zm512 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm-863-657q36 129 105 239t166 194 214 140 250 74v130q-154-21-292-83t-250-158-193-224-123-278l123-34z' fill='%23333333'%3E%3C/path%3E%3C/svg%3E"
}

Now you’ll have the icon in your command bar extension, but it’s not themed to the current site theme - so let’s fix that!

Theme support

First we’ll need fluentui if it’s not already installed in your solution, install the relevant version:

npm i @fluentui/react@7 --save

Next we’ll need to create a helper function to get the current theme color, this is a little tricky but it’s doable.

I create the following file: themeHelper.ts and add the following code:

import { ITheme, getTheme } from '@fluentui/react';

const ThemeState = (<any>window).__themeState__;

// Get theme from global UI fabric state object if exists, if not fall back to using uifabric    
export function getThemeColor(slot: string) {
    if (ThemeState && ThemeState.theme && ThemeState.theme[slot]) {
        return ThemeState.theme[slot];
    }
    const theme = getTheme();
    return theme[slot as keyof ITheme];
}

This will allow us to get the current theme color, now we need to use this in our command bar extension.

In the onInit() method of the command bar extension we’ll need to add the following code:

import { getThemeColor } from './themeHelper';
...
public onInit(): Promise<void> {
  ...

  // Get your command
  const yourCommand: Command = this.tryGetCommand('YOUR_COMMAND_NAME');

  // Get proper theme color
  const fillColor = getThemeColor("themeDarkAlt").replace('#', '%23');

  // Generate the colored icon
  const exportSvg = `data:image/svg+xml,%3Csvg xmlns%3D'http%3A//www.w3.org/2000/svg' viewBox='0 0 2048 2048'%3E%3Cpath d='M896 512h128v512H896V512zM512 768H0V256h128v274q67-123 163-221t212-166T752 37t272-37q141 0 272 36t245 103 207 160 160 208 103 245 37 272h-128q0-123-32-237t-90-214-141-182-181-140-214-91-238-32q-129 0-251 36T546 267 355 428 215 640h297v128zm512 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm0 384h1024v128H1024v-128zm-863-657q36 129 105 239t166 194 214 140 250 74v130q-154-21-292-83t-250-158-193-224-123-278l123-34z' fill='${fillColor}'%3E%3C/path%3E%3C/svg%3E`;
  
  // Set the icon
  yourCommand.iconImageUrl = exportSvg;
  
  ...
}

The important part here happens in the “Generate the colored icon” notice how we’ve replaced the %23333333 in the fill property with our own generated color.

Using template literals we can then set the color of our SVG, and then set the iconImageUrl of our command to the updated SVG - and there you go, your command bar extension now has a themed icon and will blend in with any SharePoint environment!

Themed Icon
Themed Icon

How cool is that?

TL;DR

  • Get the SVG icon you want to use
  • Encode the SVG icon
  • Set the SVG as the iconImageUrl in your command bar extension manifest
  • Replace the fill property of the SVG with the current theme color
  • Profit!